<template>
    <div class="alive">
        <button @click="switchCom">切换</button>
        <!-- keep-alive 缓存组件， 会报错组件的状态 -->
        <!-- keep-alive 使用include和exclude 需要让缓存组件暴露出一个 name, include指定缓存哪些组件， exclude指定不缓存哪些组件, max指定最大缓存数量  -->
        <!-- <keep-alive :include="['Login']"> -->
        <keep-alive :max="10" :exclude="['Register']">
            <Login v-if="flag"></Login>
            <Register v-else></Register>
        </keep-alive>
        <hr>
        <!-- transition 结合 animate.css -->
        <button @click="trans=!trans">动画</button>
        <br>
        <!-- duration 限制时长 同时限制 :duration="1000"  分开限制 :duration="{enter: 500, leave: 1000}"  -->
        <div class="colunm">
            <transition name="fade"> 
                <div v-if="trans" class="box"></div>
            </transition>
            
            <transition leave-active-class="animate__animated animate__fadeOut" enter-active-class="animate__animated animate__fadeIn"> 
                <div v-if="trans" class="box"></div>
            </transition>
            
            <transition 
                @before-enter="EnterFrom"
                @enter="EnterActive"
                @after-enter="EnterTo"
                @enter-cancelled="EnterCancel"
                @before-leave="LeaveFrom"
                @leave="LeaveActive"
                @after-leave="LeaveTo"
                @leave-cancelled="LeaveCancel"
            > 
                <div v-if="trans" class="box"></div>
            </transition>
            <!-- appear: 设置初始节点过渡，就是页面一加载完就开始的过渡，只一次 -->
            <transition 
                appear
                appear-from-class="appear-from"
                appear-active-class="appear-active"
                appear-to-class="appear-to"
            > 
                <div v-if="trans" class="box"></div>
            </transition>
            <transition 
                appear
                appear-active-class="animate__animated animate__bounceIn"
            > 
                <div v-if="trans" class="box"></div>
            </transition>
        </div>
        <hr>
        <button @click="add">ADD</button>
        <button @click="pop">pop</button>
        <br>
        <div class="wraps">
            <transition-group 
                enter-active-class="animate__animated animate__slideInDown" 
                leave-active-class="animate__animated animate__slideOutUp"
            >
                <div class="item" :key="item" v-for="item in list">{{item}}</div>
            </transition-group>
        </div>
        <hr>
        <button @click="randomChange">random</button>
        <br>
        <!-- 使用平移动画move-class -->
        <!-- transition和transition-group中还有一个属性 tag, tag="div"|tag="section", 定义包裹成什么标签,就不用再包裹一层div了 -->
        <transition-group 
            tag="div"
            class="wrap-trans"
            move-class="mmm"
        >
            <div class="items " :key="item.id" v-for="item in list2">{{item.number}}</div>
        </transition-group>
        <br>
        <!-- 数字滚动 -->
        <div>
            <input v-model="num.current" step="20" type="number">
            <div>
                {{num.tweenedNumber}}
                <!-- tofixed(2): 保留小数点后两位  -->
                {{num.tweenedNumber.toFixed(0)}}
            </div>
        </div>
    </div>
</template>

<script setup lang="ts">
import Login from './Login/index.vue'
import Register from './Register/index.vue'
import { ref, reactive, watch } from 'vue'
// lodash 引入报错是需要装ts声明文件库：npm install @types/lodash -D
import _ from 'lodash'
import 'animate.css'     // 第三方动画库
// gsap   GreenSock动画平台, 非常健全的web动画库
import gsap from 'gsap'
const EnterFrom = (el:Element) => {
    // 初始化
    gsap.set(el, {
        width: 0,
        height: 0
    })
}
const EnterActive = (el:Element, done: gsap.Callback) => {
    gsap.to(el, {
        width: 200,
        height: 200,
        onComplete: done
    })
}
const LeaveActive = (el:Element, done: gsap.Callback) => {
    gsap.to(el, {
        width: 0,
        height: 0,
        onComplete: done
    })
}

// 数字滚动
const num = reactive({
    current: 0,
    tweenedNumber: 0
})
watch(() => num.current, (nv, ov) => { 
    gsap.to(num, {               // gsap 第一个参数也可以是 一个对象
        duration: 0.5,
        tweenedNumber: nv
    })
})

// 平面过渡效果 move-class
// 生成一个数组的方式，区别 new Array 的方式，new Array(81) 会生成一个长度为81的数组，但没有占位
// 下面这种骚操作，也会生成长度为81的数组，而且每一个位置都先被 undefined占位了， as 来假设为一个数组
const list2 = ref(Array.apply(null, {length: 81} as number[]).map((_, index) => {      // 字段不用，可以以 _ 代替
    return {
        id: index,
        number: (index % 9) + 1
    }
}))
// console.log(list2.value);
const randomChange = () => {
    list2.value = _.shuffle(list2.value)
}


const list = reactive<number[]>([1, 2, 3, 4, 5, 6])
const add = () => {
    list.push(list.length + 1)
}
const pop = () => {
    list.pop()
}

// 动画的什生命周期
// const EnterFrom = (el:Element) => {
//     console.log('enter-from, 进入之前', el);
// }
// const EnterActive = (el:Element, done: Function) => {
//     console.log('enter-active, 执行过渡', el);
//     setTimeout(() => {          
//         done()            // 2秒后往下执行过渡完成， 不使用done 就是同步执行
//     }, 2000)
// }
const EnterTo = (el:Element) => {
    console.log('enter-to, 进入过渡完成', el);
}
const EnterCancel = (el:Element) => {
    console.log('enter-cancel, 多度效果被打断', el);
}

const LeaveFrom = (el:Element) => {
    console.log('leave-from, 离开之前', el);
}
// const LeaveActive = (el:Element, done: Function) => {
//     console.log('leave-active, 执行过渡', el);
//     setTimeout(() => {          
//         done()            // 2秒后往下执行过渡完成， 不使用done 就是同步执行
//     }, 3000)
// }
const LeaveTo = (el:Element) => {
    console.log('leave-to, 离开过渡完成', el);
}
const LeaveCancel = (el:Element) => {
    console.log('leave-cancel, 多度效果被打断', el);
}

let trans = ref<boolean>(true)


let flag = ref(true)
const switchCom = () => {
    flag.value = !flag.value
}
</script>

<style lang="less" scoped>
.mmm {
    transition: all 1s;
}
.alive {
    margin-top: 30px;
    margin-left: 300px;
    overflow: auto;
    .colunm {
        display: flex;
        justify-content: space-around;
    }
    .wraps {
        display: flex;
        flex-wrap: wrap;
        border: 1px solid #536456;
        word-break: break-all;          // 文本强制换行会截断单词，  break-word: 不会截断单词按单词换行
        .item {
            margin: 10px;
        }
    }
    .wrap-trans {
        display: flex;
        flex-wrap: wrap;
        width: calc(25px * 10 + 9px);
        .items {
            width: 25px;
            height: 25px;
            border: 1px solid #864564;
            line-height: 23px;
            text-align: center;
        }
    }
}
.box {
    width: 150px;
    height: 150px;
    background-color: plum;
}

.fade-enter-from {
    width: 0;
    height: 0;
    background-color: lightcoral;
}
.fade-enter-active {
    transition: all 2s ease;
}
.fade-enter-to {
    width: 150px;
    height: 150px;
    background-color: plum;
}
.fade-leave-from {
    width: 150px;
    height: 150px;
    background-color: plum;
}
.fade-leave-active {
    transition: all 1s ease-in;
}
.fade-leave-to {
    width: 0;
    height: 0;
    background-color: lightcoral;
}
.appear-from {
    width: 0;
    height: 0;
}
.appear-active {
    transition: all 0.5s ease-out;
}
.appear-to {
    width: 150px;
    height: 150px;
}
</style>